package com.yuezheng.modules.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yuezheng.modules.httpclient.HttpClient;
import me.zhengjie.utils.StringUtils;
import me.zhengjie.zabbix.Request;
import me.zhengjie.zabbix.RequestBuilder;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by bruce on 19/7/11.
 */
@Service
@Configuration
public class ZabbixApiImpl implements com.yuezheng.modules.system.service.ZabbixApi {

    @Value("${zabbix.url}")
    private String url;

    @Value("${zabbix.username}")
    private String username;

    @Value("${zabbix.password}")
    private String password;

    @Autowired
    private HttpClient httpClient;

    /** 默认字符集 */
    public static final String DEFAULT_CHARSET = "UTF-8";

    @Autowired
    private CloseableHttpClient closeableHttpClient;

    @Autowired
    private RequestConfig config;

    private volatile String auth;

    private volatile String zbx_sessionid;

    private String PHPSESSID = "";


    @Override
    public String apiVersion() {
        Request request = RequestBuilder.newBuilder()
                .method("apiinfo.version").build();
        JSONObject object = this.call(request);
        return object.getString("result");
    }

    public String getAuth() {
        if(this.auth == null) {
            this.login();
        }
        return this.auth;
    }


    @Override
    public JSONObject call(Request request) {
        if(this.auth == null) {
            this.login();
        }

        if(this.auth != null){
            request.setAuth(this.auth);
            try {
                HttpClient.HttpResponse response = httpClient.doPost(this.url,request);
                String body = response.getBody();
                return  (JSONObject) JSONObject.parse(body);
            } catch (Exception e) {
                throw new RuntimeException("DefaultZabbixApi call exception!", e);
            }
        }
        throw new RuntimeException("DefaultZabbixApi call exception, auth is null!");
    }

    @Override
    public CloseableHttpResponse graphImage(Map<String,String> params) {
        if(StringUtils.isEmpty(this.zbx_sessionid))
            this.webLogin();

        String prefix =  url.substring(0,url.lastIndexOf("/"));
        String postUrl = String.format("%s/chart2.php?graphid=%s&period=%s&stime=%s&isNow=1&profileIdx=web.graphs&profileIdx2=%s&width=1256&sid=554d7d258415c00a&screenid=&curtime=%s",
                prefix,
                params.get("graphId"),
                params.get("period"),
                params.get("stime"),
                params.get("graphId"),
                String.valueOf(System.currentTimeMillis())
                );

        HttpGet httpPost = new HttpGet(postUrl);
        httpPost.setConfig(config);

        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType());
        String cookie = String.format("PHPSESSID=%s; zbx_sessionid=%s; SL_G_WPT_TO=zh; SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1",
                PHPSESSID,zbx_sessionid);
        httpPost.setHeader("Cookie", cookie);

        try {
            System.out.println(httpPost.toString());
            CloseableHttpResponse response = this.closeableHttpClient.execute(httpPost);
            if(response.getStatusLine().getStatusCode()==200) {
                return response;
            }
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return null ;
    }

    @Override
    public boolean login() {
        this.auth = null;
        Request request = RequestBuilder.newBuilder()
                .paramEntry("user", this.username)
                .paramEntry("password", this.password)
                .method("user.login").build();
        //JSONObject response = call(request);
        try {
            HttpClient.HttpResponse response = httpClient.doPost(this.url,request);
            JSONObject json = (JSONObject) JSONObject.parse(response.getBody());
            String auth = json.getString("result");
            if (auth != null && !auth.isEmpty()) {
                this.auth = auth;
                return true;
            }
        } catch (Exception e) {
            throw new RuntimeException("DefaultZabbixApi call exception!", e);
        }
        return false;
    }

    @Override
    public boolean webLogin() {
        String prefix =  url.substring(0,url.lastIndexOf("/"));
        String postUrl = prefix + "/" + "index.php";
        HttpPost httpPost = new HttpPost(postUrl);
        httpPost.setConfig(config);

        httpPost.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.getMimeType());
        //httpPost.addHeader("Cookie", "PHPSESSID=26egjf9sbbkspdrvc5ar9tgcp4; zbx_sessionid=73167a24e595bc81554d7d258415c00a");

        String requestBody = String.format("name=%s&password=%s&autologin=1&enter=Sign+in",username,password);
        StringEntity postEntity = new StringEntity(requestBody, "UTF-8");
        httpPost.setEntity(postEntity);
        try {
            BasicCookieStore cookieStore = new BasicCookieStore();
            HttpClientBuilder clientbuilder = HttpClients.custom().setDefaultCookieStore(cookieStore);
            CloseableHttpClient httpclient = clientbuilder.build();
            CloseableHttpResponse response =httpclient.execute(httpPost);
            if(response.getStatusLine().getStatusCode()==302) {
                List list = cookieStore.getCookies();

                System.out.println("list of cookies");
                Iterator it = list.iterator();
                if(it.hasNext()){
                    BasicClientCookie cookie = (BasicClientCookie)it.next();
                    if(cookie.getName().equals("zbx_sessionid"))
                        zbx_sessionid = cookie.getValue();
                    if(cookie.getName().equals("PHPSESSID"))
                        PHPSESSID = cookie.getValue();
                }

                String location = "";
                for(Header header: response.getAllHeaders()) {
                    if(header.getName().equals("Location")) {
                        location = header.getValue();
                        break;
                    }
                }
                if(location.length() > 0 ) {
                    cookieStore.clear();
                    response.close();

                    HttpGet get = new HttpGet(prefix + "/" + location);
                    get.setConfig(config);
                    response = httpclient.execute(get);
                    for(Object co: cookieStore.getCookies().toArray()){
                        BasicClientCookie cookie = (BasicClientCookie)co;
                        if(cookie.getName().equals("PHPSESSID"))
                            PHPSESSID = cookie.getValue();
                    }
                }
                return true;
            }
        }catch(Exception ex){
            ex.printStackTrace();
            return false ;
        }
        return false;
    }

    @Override
    public JSONArray hostGroup_Get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .method("hostgroup.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public JSONArray host_Get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                //.paramEntry("selectInterfaces","extend")
                .method("host.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public Integer host_get_count(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                //.paramEntry("selectInterfaces","extend")
                .method("host.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getInteger("result");
    }

    @Override
    public JSONArray graph_get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                .method("graph.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public JSONArray trigger_Get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                .method("trigger.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public JSONArray dashboard_HoststatGet(Map<String, Object> filter) {
        Request request = RequestBuilder.newBuilder().paramEntry("output","extend")
                .paramEntry("selectWidgets","['hoststat']")
                .method("dashboard.get")
                .build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public JSONArray hostinterface_get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                .method("hostinterface.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public Integer hostinterface_get_count(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                //.paramEntry("output","extend")
                .method("hostinterface.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getInteger("result");
    }

    @Override
    public JSONArray problem_get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                .method("problem.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public Integer problem_get_count(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                //.paramEntry("selectInterfaces","extend")
                .method("problem.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getInteger("result");
    }

    @Override
    public JSONArray trend_get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                .method("trend.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }

    @Override
    public JSONArray event_get(Map<String, Object> filter) {
        RequestBuilder requestBuilder = RequestBuilder.newBuilder()
                .paramEntry("output","extend")
                .method("event.get");
        for(Map.Entry<String,Object> item: filter.entrySet()) {
            requestBuilder.paramEntry(item.getKey(), item.getValue());
        }
        Request request = requestBuilder.build();
        JSONObject object = this.call(request);
        return object.getJSONArray("result");
    }
}
